#ifndef __COMM_HPP__ // 避免重定义
#define __COMM_HPP__

using namespace std;
#include <sys/types.h>
#include <sys/ipc.h>
#include <string.h>
#include <errno.h>
#include <iostream>
#include <sys/shm.h>
#include <sys/stat.h>
#include <cassert>

#define PATHNAME "."
#define POJID 0x89   

//共享内存的大小是以PAGE页（4KB）为单位（多线程）
const int size = 2048;//假设4097 系统给你8kb 这个内存不能全用，申请多少就用多少

// key_t ftok(const char *pathname, int proj_id);
key_t getKey()
{
    key_t k = ftok(PATHNAME, POJID); // 当前路径和随机id 生成一随机的shmid
    if (k == -1)
    {
        cerr << "error:" << errno << ":" << strerror(errno) << endl;
        exit(1);
    }
    return k;
}

string toHex(int x)
{
    char buf[64];
    snprintf(buf, sizeof buf, "0x%x", x); // 将x以%x的形式去写入buf
    return buf;
}

static int createshmassist(key_t k, int size, int flag) // 辅助创建共享内存
{
    int shmid = shmget(k, size, flag); // 创建共享内存 并返回共享内存的id
    if (shmid == -1)
    {
        cerr << "error:" << errno << ":" << strerror(errno) << endl;
        exit(0);
    }
    return shmid;
}

int createshm(key_t k, int size)
{
    umask(0); // 权限设0 只对当前进程有效
    return createshmassist(k, size, IPC_CREAT | IPC_EXCL | 0666);
    // IPC_CREAT | IPC_EXCL 两个一起用就是有就报错，没有就创建，保证是最新的共享内存
}

int getshm(key_t k, int size) // 获取共享内存
{
    return createshmassist(k, size, IPC_CREAT); // IPC_CREAT单独使用有就获取，没有就创建
}

char *attachshm(int shmid)
{
    char *begin = (char *)shmat(shmid, nullptr, 0);  //shmat链接共享内存并返回起始地址 nullptr：系统决定链接
    return begin;
}

void detachshm(char *begin)//取消关联
{
    int n = shmdt(begin);//如果为空就是系统取消挂接，现在是取消挂接到指定的共享内存
    assert(n != -1);
    (void)n;
}
void delshm(int shmid)
{
    int n = shmctl(shmid, IPC_RMID, nullptr); //IPC_SET：写入结构题成员   IPC_RMID:销毁   IPC_INFO：更新结构体成员
    assert(n != -1); 
    (void)n;
}
#define SERSVE  1
#define CLIENT  2



class IT
{
    public:
    IT(int t):type(t)
    {
       key_t k=getKey();
       if(type==SERSVE)shmid=createshm(k,size);
       else shmid=getshm(k,size);
       begin=attachshm(shmid);

        

    }
    char*getBegin(){return begin;}
    ~IT()
    {
        detachshm(begin);
        if(type==SERSVE)delshm(shmid);

    }
    private:
    char *begin;
    int type;
    int shmid;


};




#endif